<template>
    <div class="box">
        <!-- 面包屑导航区 -->
        <t-breadcrumb :maxItemWidth="'150'">
            <t-breadcrumbItem :to="{ path: '/dashboard' }">首页</t-breadcrumbItem>
            <t-breadcrumbItem>商品管理</t-breadcrumbItem>
            <t-breadcrumbItem :maxWidth="'160'">添加商品</t-breadcrumbItem>
        </t-breadcrumb>

        <!-- 卡片视图区域 -->
        <t-card> 
            <!-- 提示区域 -->
            <t-alert theme="info" message="添加商品信息" />
            <!-- 步骤条区域 -->
            <t-steps :current="activeIndex" readonly>
                <t-step-item title="基本信息"></t-step-item>
                <t-step-item title="商品参数"></t-step-item>
                <t-step-item title="商品属性"></t-step-item>
                <t-step-item title="商品图片"></t-step-item>
                <t-step-item title="商品内容"></t-step-item>
                <t-step-item title="完成"></t-step-item>
            </t-steps>
            <!-- tab 栏区域 -->
            <t-form :data="addForm" :rules="addFormRules" ref="addFormRef" labelAlign="top" :onSubmit="add">
                <t-tabs v-model="activeIndex" placement="left" :onChange="beforeTabLeave">
                    <t-tab-panel :value="0" label="基本信息">
                        <t-form-item label="商品名称" name="goods_name">
                            <t-input v-model="addForm.goods_name" placeholder="请输入商品名称"></t-input>
                        </t-form-item>
                        <t-form-item label="商品价格" name="goods_price">
                            <t-input-number v-model="addForm.goods_price" :min="0" theme="normal" align="right">
                                <template #suffix><span>元</span></template>
                            </t-input-number>
                        </t-form-item>
                        <t-form-item label="商品重量" name="goods_weight">
                            <t-input-number v-model="addForm.goods_weight" theme="normal" align="right">
                                <template #suffix><span>KG</span></template>
                            </t-input-number>
                        </t-form-item>
                        <t-form-item label="商品数量" name="goods_number">
                            <t-input-number v-model="addForm.goods_number" theme="normal" align="right">
                                <template #suffix><span>个</span></template>
                            </t-input-number>
                        </t-form-item>
                        <t-form-item label="商品分类" name="goods_cat">
                            <t-cascader v-model="addForm.goods_cat" value-type="full" :options="cateList" :keys="cateProps"
                                trigger="hover" @change="handleChange" clearable />
                        </t-form-item>
                    </t-tab-panel>
                    <t-tab-panel :value="1" label="商品参数">
                        <!-- 渲染表单的 Item 项 -->
                        <t-form-item :label="item.attr_name" v-for="item in manyTableData" :key="item.attr_id">
                            <t-checkbox-group v-model="item.attr_vals" :options="item.attr_vals"></t-checkbox-group>
                        </t-form-item>
                    </t-tab-panel>
                    <t-tab-panel :value="2" label="商品属性">
                        <t-form-item :label="item.attr_name" v-for="item in onlyTableData" :key="item.attr_id">
                            <t-input v-model="item.attr_vals"></t-input>
                        </t-form-item>
                    </t-tab-panel>
                    <t-tab-panel :value="3" label="商品图片">
                        <!-- 图片上传组件 -->
                        <t-upload v-model="files" placeholder="支持批量上传图片文件" theme="image-flow" :headers="headerObj"
                            accept="image/*" multiple :action="uploadURL" auto-upload :max="8" :abridge-name="[6, 6]"
                            :onSuccess="handleSuccess" :onRemove="handleRemove"></t-upload>
                    </t-tab-panel>
                    <t-tab-panel :value="4" label="商品内容">
                        <quill-editor v-model="addForm.goods_introduce"></quill-editor>
                        <!-- 按钮区域 -->
                        <t-space>
                            <t-button class="btnAdd" type="submit">添加商品</t-button>
                            <t-button class="btnAdd" theme="default" @click="cancelAdd">取消添加</t-button>
                        </t-space>
                    </t-tab-panel>
                </t-tabs>
            </t-form>
        </t-card>

    </div>
</template>

<script>
export default {

    components: {

    },

    created() {
        this.getCateList()
    },

    data() {
        return {
            // 激活的步骤
            activeIndex: 0,
            // 添加商品的表单数据对象
            addForm: {
                goods_name: '',
                goods_price: 0,
                goods_weight: 0,
                goods_number: 0,
                // 商品所属的分类数组
                goods_cat: [],
                // 商品的图片数组
                pics: [],
                // 商品的详细描述
                goods_introduce: '',
                attrs: [],
            },
            // 添加商品的表单规则校验对象
            addFormRules: {
                goods_name: [
                    {
                        required: true,
                        message: '请输入商品名称',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '商品名称不能为空' },
                    {
                        min: 2,
                        message: '至少需要两个字符，一个中文等于两个字符',
                        type: 'error',
                        trigger: 'blur',
                    },
                ],
                goods_price: [
                    {
                        required: true,
                        message: '请输入商品价格',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '商品价格不能为空' },
                    { min: 0, type: 'error', trigger: 'blur', message: '必须为非负数' }
                ],
                goods_weight: [
                    {
                        required: true,
                        message: '请输入商品重量',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '商品重量不能为空' },
                    { min: 0, type: 'error', trigger: 'blur', message: '必须为非负数' }
                ],
                goods_number: [
                    {
                        required: true,
                        message: '请输入商品数量',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '商品数量不能为空' },
                    { min: 0, type: 'error', trigger: 'blur', message: '必须为非负数' }
                ],
                goods_cat: [
                    {
                        required: true,
                        message: '请选择商品分类',
                        type: 'error',
                    },
                ],
            },
            // 存储商品分类列表对象
            cateList: [],
            // 级联选择器自定义属性对象
            cateProps: {
                label: 'cat_name',
                value: 'cat_id',
                children: 'children'
            },
            // 动态参数列表表格数据
            manyTableData: [],
            // 静态属性列表表格属性
            onlyTableData: [],
            // 判断是否获取了商品参数
            isGetManyTableData: false,
            // 判断是否获取了商品属性
            isGetOnlyTableData: false,
            // 上传图片的 URL 地址
            uploadURL: 'http://127.0.0.1:8888/api/private/v1/upload',
            // 图片上传组件的headers请求头对象
            headerObj: {
                Authorization: window.sessionStorage.getItem('token'),
            },
            // 接收批量上传的图片文件
            files: [],
        }
    },

    methods: {

        // 获取所有商品分类数据
        async getCateList() {
            const { data: res } = await this.$http.get('categories')
            if (res.meta.status !== 200) {
                this.$message.error('获取商品分类失败！')
            } else {
                // 把数据列表赋值给 cateList
                this.cateList = res.data
            }
        },

        // 级联选择器选中项变化时触发次函数
        handleChange() {
            if (this.addForm.goods_cat.length !== 3) {
                this.addForm.goods_cat = []
            }
        },
        async beforeTabLeave(activeName) {

            // 阻止标签栏的切换
            if (this.activeIndex !== 0 && this.addForm.goods_cat.length !== 3) {
                this.activeIndex = 0
                this.$message.error('请先选择商品分类！')
                return
            }

            // 证明访问的是动态参数面板
            if (activeName === 1) {
                const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
                    params: { sel: 'many' }
                })
                if (res.meta.status !== 200) {
                    this.$message.error('获取动态参数列表失败！')
                } else {
                    res.data.forEach(item => {
                        item.attr_vals = item.attr_vals.length === 0 ? [] : item.attr_vals.split(' ')
                    })
                    this.manyTableData = res.data
                    this.isGetManyTableData = true
                }
            } else if (activeName === 2) {
                const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
                    params: { sel: 'only' }
                })
                if (res.meta.status !== 200) {
                    this.$message.error('获取静态属性列表失败！')
                } else {
                    this.onlyTableData = res.data
                    this.isGetOnlyTableData = true
                }
            }
        },

        // 文件上传成功时调用
        handleSuccess(res) {

            // 支持多张图片一起上传 for 遍历
            for (let index = 0; index < res.response.length; index++) {

                // 1. 拼接得到一个图片信息对象
                const picInfo = {

                    pic: res.response[index].data.tmp_path,
                }

                // 2.将图片信息对象，push 到 pics 数组中
                this.addForm.pics.push(picInfo)
            }
        },
        // 移除文件时调用
        handleRemove(res) {
            // 1. 获取将要删除的图片都临时路径
            const filePath = res.file.response.data.tmp_path
            // 2. 从 pics 数组中，找到这个图片对应的索引值
            const i = this.addForm.pics.findIndex(x => {
                x.pic === filePath
            })
            // 3. 调用数组的 splice 方法，把图片信息对象，从 pics 数组中移除
            this.addForm.pics.splice(i, 1)
        },

        // 添加之前的预校验函数
        validate() {
            // 提交前的预校验 - 商品名称
            if (this.addForm.goods_name.length === 0) {
                this.$message.error('请输入商品名称')
                return false
            }

            if (this.addForm.goods_name.trim().length === 0 && this.addForm.goods_name.length > 0) {
                this.$message.error('商品名称不能为空！')
                return false
            }

            if (this.addForm.goods_name.trim().length < 2) {
                this.$message.error('商品名称至少需要两个字符，一个中文等于一个字符')
                return false
            }

            // 提交前的预校验 - 商品价格
            if (this.addForm.goods_price < 0) {
                this.$message.error('商品价格不能为负数！')
                return false
            }

            // 提交前的预校验 - 商品重量
            if (this.addForm.goods_weight < 0) {
                this.$message.error('商品重量不能为负数！')
                return false
            }

            // 提交前的预校验 - 商品数量
            if (this.addForm.goods_number < 0) {
                this.$message.error('商品数量不能为负数！')
                return false
            }

            return true
        },

        // 深拷贝函数
        deepCopy(obj) {
            if (obj === null || typeof obj !== 'object') {
                return obj
            }

            let copy = Array.isArray(obj) ? [] : {}

            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    copy[key] = this.deepCopy(obj[key])
                }
            }

            return copy
        },

        // 点击按钮，添加商品
        async add() {

            // 执行添加前的预校验
            if (!this.validate()) return

            // 校验通过 执行添加的业务逻辑

            if (!this.isGetManyTableData) {
                this.$message.error('请先完成商品参数！')
                return
            }

            if (!this.isGetOnlyTableData) {
                this.$message.error('请先完成商品属性！')
                return
            }

            // 处理动态参数
            this.manyTableData.forEach(item => {
                const newInfo = {
                    attr_id: item.attr_id,
                    attr_value: item.attr_vals.join(' ')
                }
                this.addForm.attrs.push(newInfo)
            })

            // 处理静态属性
            this.onlyTableData.forEach(item => {
                const newInfo = {
                    attr_id: item.attr_id,
                    attr_value: item.attr_vals
                }
                this.addForm.attrs.push(newInfo)
            })

            // 调用 deepCopy 执行深拷贝
            const form = this.deepCopy(this.addForm)

            form.goods_cat = form.goods_cat.join(',')

            // 发起请求添加商品
            // 商品的名称必须是唯一的
            const { data: res } = await this.$http.post('goods', form)

            if (res.meta.status !== 201) {
                this.$message.error('添加商品失败！')
            } else {
                this.$message.success('添加商品成功！')
                this.$router.push('/goods')
            }

        },
        // 点击按钮，取消添加
        cancelAdd() {
            this.$router.push('/goods')
        },

    },

    computed: {
        cateId() {
            if (this.addForm.goods_cat.length === 3) {
                return this.addForm.goods_cat[2]
            }

            return null
        }
    },

    // 监听 files 文件数组 补充url属性供预览使用
    watch: {
        files() {
            for (let index = 0; index < this.files.length; index++) {
                this.files[index].url = this.files[index].response.data.url
            }
        },
    },

}
</script>

<style lang="less" scoped>
.box {
    padding: 15px;

    .t-tab-panel {
        padding-left: 10px;
    }

    /deep/ .t-checkbox {
        border: 1px solid #0052d9;
        padding: 5px 10px;
        border-radius: 5px;
    }

    .btnAdd {
        margin-top: 15px;
    }

    .t-input-number {
        width: 100%;
    }
}
</style>